package com.zhenhunfan.hello.rpc.demo05;

import com.zhenhunfan.hello.rpc.common.IUserService;
import com.zhenhunfan.hello.rpc.common.User;

import java.io.DataInputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.Socket;

/**
 * <p>Title: Sub</p>
 * <p>Description: 客户端网络请求的代理</p>
 *
 * @author zhenhunfan
 * @version 1.0.0
 * @date 2021/4/8
 */
public class Stub {
    public static IUserService getStub(){
        /*
            proxy： 代理的对象
            method： 代理的对象正在执行的方法
            args: 方法的参数
         */
        InvocationHandler h = new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //1.建立连接
                Socket socket = new Socket("localhost", 9000);

                //2.往Server端写数据
                ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                String methodName = method.getName();
                //为了避免方法重载，把方法的参数类型传递给server
                Class<?>[] parameterTypes = method.getParameterTypes();
                oos.writeUTF(methodName);
                oos.writeObject(parameterTypes);
                oos.writeObject(args);
                oos.flush();

                //3.从Server端读数据
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                User user = (User)ois.readObject();

                oos.close();
                socket.close();
                return user;
            }
        };

        /*
            Proxy.newProxyInstance ：new出来一个代理类对象
            IUserService.class.getClassLoader() ：产生代理类的class loader
            new Class[]{IUserService.class} : 这个代理类实现了哪些接口
            h；调用动态代理类方法的处理器，h 实例化的时候（上面代码），invoke方法在动态代理类的所有方法执行的时候都会执行
        */
        Object o = Proxy.newProxyInstance(IUserService.class.getClassLoader(), new Class[]{IUserService.class}, h);
        //通过反射可以看看这个代理类的相关信息
        System.out.println(o.getClass().getName());
        System.out.println(o.getClass().getInterfaces()[0]);
        return (IUserService)o;
    }
}
